package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.async.CartAsyncService;
import com.atguigu.gmall.cart.mapper.CartInfoMapper;
import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private CartInfoMapper cartInfoMapper;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CartAsyncService cartAsyncService;

    /**
     * 添加购物车
     *
     * @param skuId
     * @param userId
     * @param skuNum
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addToCart(Long skuId, String userId, Integer skuNum) {
        CartInfo cartInfo = null;

        String cartKey = getCartKey(userId);
//        购物车的数据在缓存中不存在
        if (!redisTemplate.hasKey(cartKey)) {
            loadCartInfoSql(userId);
        }
        try {
//            从redis 中获取购物车数据
            cartInfo = (CartInfo) redisTemplate.boundHashOps(cartKey).get(skuId.toString());

            if (cartInfo != null) {
                //        查询商品信息
                SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
                //            添加数量和更新实时价格
                cartInfo.setSkuNum(cartInfo.getSkuNum() + skuNum);

                cartInfo.setSkuPrice(skuInfo.getPrice());
                cartInfo.setUpdateTime(new Timestamp(new Date().getTime()));

                cartAsyncService.updateCartInfo(cartInfo);
            } else {
                //        查询商品信息
                SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
                //            添加购物车数据
                CartInfo cart = new CartInfo();
                cart.setSkuId(skuInfo.getId());
                cart.setImgUrl(skuInfo.getSkuDefaultImg());
                cart.setSkuName(skuInfo.getSkuName());
                cart.setUserId(userId);
                cart.setIsChecked(1);
                cart.setCartPrice(skuInfo.getPrice());
                cart.setSkuPrice(skuInfo.getPrice());
                cart.setSkuNum(skuNum);
                cart.setUpdateTime(new Timestamp(new Date().getTime()));
                cart.setCreateTime(new Timestamp(new Date().getTime()));
                cartAsyncService.saveCartInfo(cart);

                //            赋值购物车数据
                cartInfo = cart;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        //        添加数据到缓存
        setRedisCach(cartKey, skuId, cartInfo);
//        设置过期时间
        setExpireTime(cartKey);
    }

    /**
     * 通过用户Id 查询购物车列表
     *
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {

        List<CartInfo> cartInfoList = null;

//        查询用户数据购物车
        if (!StringUtils.isEmpty(userId)) {
//            合并购物车数据
            if (StringUtils.isEmpty(userTempId)) {
//                查询登录用户车数据
                cartInfoList = cartInfoList(userId);
                return cartInfoList;
            } else {
//                查询未登录用户购物车数据
                cartInfoList = cartInfoList(userTempId);
                if (CollectionUtils.isNotEmpty(cartInfoList)) {
                    //                合并购物车数据
                    List<CartInfo> totalCartInfoList = totalCartInfoList(cartInfoList, userId);
//                删除未登录用户数据
                    deleteUserTempIdCartInfo(userTempId);
                } else {
//                查询登录用户的数据
                    cartInfoList = cartInfoList(userId);
                }
            }
        }else {
//            查询未登录用户数据
            cartInfoList = cartInfoList(userTempId);
        }
        return cartInfoList;
    }

    //                删除未登录用户数据
    private void deleteUserTempIdCartInfo(String userTempId) {
//        删除数据
        cartAsyncService.deleteCarInfo(userTempId);

//        删除redis中数据
        String cartKey = getCartKey(userTempId);
        if (redisTemplate.hasKey(cartKey)) {
            redisTemplate.delete(cartKey);
        }
    }

    //                合并购物车数据
    private List<CartInfo> totalCartInfoList(List<CartInfo> cartInfoNoLoginList, String userId) {
//        查询登录的用户购物车数据
        List<CartInfo> cartInfoLoginList = this.cartInfoList(userId);
//        转化为map集合，key为skuId，value为CartInfo
        Map<Long, CartInfo> longCartInfoMap = cartInfoLoginList.stream()
                .collect(Collectors.toMap(CartInfo::getSkuId, cartInfo -> cartInfo));
//        找出与skuId相等的数据
        for (CartInfo cartInfo : cartInfoNoLoginList) {
            Long skuId = cartInfo.getSkuId();
            if (longCartInfoMap.containsKey(skuId)) {
//                将购物车数量加一
                CartInfo cartLoginInfo = longCartInfoMap.get(skuId);
                cartLoginInfo.setSkuNum(cartLoginInfo.getSkuNum() + cartInfo.getSkuNum());

//                判断购物车勾选状态
                if (cartInfo.getIsChecked() == 1) {
                    cartLoginInfo.setIsChecked(1);
                }
//                修改购物车数据
                cartInfo.setUpdateTime(new Timestamp(new Date().getTime()));
                UpdateWrapper<CartInfo> wrapper = new UpdateWrapper<>();
                wrapper.set("user_id", cartLoginInfo.getUserId());
                wrapper.set("sku_id", cartLoginInfo.getSkuId());
                cartInfoMapper.update(cartInfo, wrapper);

            } else {
//                不包含添加购物车数据
                cartInfo.setUserId(userId);
                cartInfo.setCreateTime(new Timestamp(new Date().getTime()));
                cartInfo.setUpdateTime(new Timestamp(new Date().getTime()));
                cartInfoMapper.insert(cartInfo);
            }
        }
//        返回合并的数据
        List<CartInfo> cartInfoList = this.loadCartInfoSql(userId);
        return cartInfoList;
    }

    //        查询用户数据购物车
    private List<CartInfo> cartInfoList(String userId) {

        List<CartInfo> cartList = new ArrayList<>();

//        先从redis中获取数据
        String cartKey = getCartKey(userId);
//                获取购物车集合数据
        cartList = redisTemplate.opsForHash().values(cartKey);

        if (CollectionUtils.isEmpty(cartList)) {
//            从数据库中获取数据中获取数据
            cartList = loadCartInfoSql(userId);
        }
//            直接返回数据按照修改数据进行排序
        cartList.sort(new Comparator<CartInfo>() {
            @Override
            public int compare(CartInfo o1, CartInfo o2) {
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            }
        });
        return cartList;
    }

    //            从数据库中获取数据中获取数据
    public List<CartInfo> loadCartInfoSql(String userId) {
        //            查询购物车数据
        QueryWrapper<CartInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.orderByDesc("update_time");
        List<CartInfo> cartInfos = cartInfoMapper.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(cartInfos)) {
//            存储购物车数据
            HashMap<String, CartInfo> map = new HashMap<>();
//                把购物车数据放入缓存
            String cartKey = getCartKey(userId);
//            更新实时价格
            for (CartInfo cartInfo : cartInfos) {
                cartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));
//                redisTemplate.opsForHash().put(cartKey, cartInfo.getSkuId().toString(), cartInfo);
                map.put(cartInfo.getSkuId().toString(), cartInfo);
                redisTemplate.opsForHash().putAll(cartKey, map);
            }
            //               过期时间
            setExpireTime(cartKey);
            return cartInfos;
        }
        return new ArrayList<>();
    }

    /**
     * 更新选中状态
     *
     * @param userId
     * @param isChecked
     * @param skuId
     */
    @Override
    public void checkCart(String userId, Integer isChecked, Long skuId) {
//        更新数据库中数据
        cartAsyncService.checkCart(userId, isChecked, skuId);

//        更新redis中数据
        String cartKey = getCartKey(userId);
        Boolean flag = redisTemplate.boundHashOps(cartKey).hasKey(skuId.toString());
        if (flag) {
            //        获取数据
            CartInfo cartInfo = (CartInfo) redisTemplate.boundHashOps(cartKey).get(skuId.toString());
            cartInfo.setIsChecked(isChecked);
//            存入redis中
            redisTemplate.boundHashOps(cartKey).put(skuId.toString(), cartInfo);
//            设置过期时间
            setExpireTime(cartKey);
        }
    }

    /**
     * 删除购物车某一个
     *
     * @param userId
     * @param skuId
     */
    @Override
    public void deleteCartInfo(String userId, Long skuId) {
        cartAsyncService.deleteCartInfo(userId, skuId);
//        删除redis中数据
        String cartKey = getCartKey(userId);
        if (redisTemplate.boundHashOps(cartKey).hasKey(skuId.toString())) {
            redisTemplate.boundHashOps(cartKey).delete(skuId.toString());
        }

    }

    /**
     * 查询订单列表清单
     */
    @Override
    public List<CartInfo> cartList(String userId) {

//        从redis 中获取数据
        String cartKey = getCartKey(userId);
        List<CartInfo> cartInfos = redisTemplate.boundHashOps(cartKey).values();
//        判断是否选中isChecked = 1
        List<CartInfo> cartInfoList = cartInfos.stream().filter(cartInfo ->
                cartInfo.getIsChecked().intValue() == 1).collect(Collectors.toList());
        return cartInfoList;
    }

    //    设置用户购物车数据cartKey
    private String getCartKey(String userId) {
        String cartKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        return cartKey;
    }

    //        设置过期时间
    private void setExpireTime(String cartKey) {
        redisTemplate.expire(cartKey, RedisConst.USERKEY_TIMEOUT, TimeUnit.SECONDS);
    }

    //    设置数据缓存
    private void setRedisCach(String cartKey, Long skuId, CartInfo cartInfo) {
        redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfo);
    }
}
